home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / pdclk145.zip / ARP.ASM next >
Assembly Source File  |  1992-10-03  |  16KB  |  653 lines

  1. ;        arp.asm
  2. ;========================================================================
  3.  
  4. ; Copyright (C) 1991 by Jan.Engvald@ldc.lu.se, see file COPYING.
  5.  
  6. ArpStruc    struc
  7. iArpHtype    dw    0            ; 0001 = Ether
  8. iArpProt    dw    0008h            ; 0800 = IP
  9. iArpHlen    db    0            ; Hw addr length
  10. iArpPlen    db    4            ; IP addr length
  11. iArpOp        dw    0100h            ; 0001 = request
  12. iArpMyHwAd    db    2*16+2*4 dup (0)
  13. ArpBodyLen    =    $-iArpHtype
  14. ArpStruc    ends
  15.  
  16. ArpBegLen    equ    iArpMyHwAd+8-iArpHtype
  17.  
  18. ArpHandle    dw    0
  19.  
  20. ifndef        ARPSLOTS
  21. ARPSLOTS    equ    12
  22. endif
  23.  
  24. ; The arp table contains information on hosts on this net.
  25. ; Slot 0, 1 and 2 (index 0, 2 and 4) are static and contain:
  26. ; this net broadcast, this subnet broadcast and my address, respectively.
  27. ;
  28. ; If we don't RECEIVE packets for more than a minute from a host or gateway,
  29. ; its slot is cleared. If we then DO receive a packet, the slot is restored
  30. ; by VerifyIpHdr without sending an ARP. On the other hand, if WE want to
  31. ; send the next packet, we will do an ARP and can thus detect dead hosts
  32. ; or gateways.
  33.         even
  34. ArpTabIp2    dw    ARPSLOTS dup (0ffffh)    ; IP # (last part)
  35. ArpTabIp1    dw    ARPSLOTS dup (0ffffh)    ; IP # (first part)
  36. ArpTabTr    dw    ARPSLOTS dup (0)    ; timer
  37. ArpTabFlags    dw    ARPSLOTS dup (0)    ; flags
  38. ArpTabTrSq    dw    ARPSLOTS dup (0)    ; source quench timer
  39. ArpTabSqDelay    dw    ARPSLOTS dup (0)    ; source quench delay
  40. ArpTabHwAdr    db    ARPSLOTS*16 dup (0ffh)    ; hardware addr (max 16 bytes)
  41. ArpTabHw3    dw    ARPSLOTS dup (0ffffh)    ; hw addr for reverse lookup
  42. ArpTabHw2    dw    ARPSLOTS dup (0ffffh)    ; hw addr for reverse lookup
  43. ArpTabHw1    dw    ARPSLOTS dup (0ffffh)    ; hw addr for reverse lookup
  44. USE_SNAP    equ    1            ; bit in ArpTabFlags
  45. SQ_UPDATED    equ    2            ; bit in ArptabFlags/RouteTabFl
  46.  
  47. ARPMYIDX    equ    4
  48. ArpPutSlot    dw    ARPMYIDX
  49.  
  50. ArpType     dw    0608h
  51. ArpBuf        ArpStruc    <>
  52.  
  53. ArpFixedLen    equ    $-ArpType
  54. aArpOffsSrcIp    equ    iArpMyHwAd+2-iArpHtype    ; *test*
  55. MyHwAd        equ    ArpBuf.iArpMyHwAd
  56. ProtType    equ    ArpBuf.iArpProt
  57. ArpFixedPart    equ    ArpType
  58.  
  59. if DEBUG
  60. DbgIntCnt    db    1
  61. endif ; DEBUG
  62.  
  63. ;************************************************************************
  64. ;*        ArpFindIp
  65. ;*
  66. ;*    Input:        DX = first word of IP # (saved)
  67. ;*            AX = second word of IP # (saved)
  68. ;*            A PushfDI must be done before calling
  69. ;*    Output:     if found: zero and DI = arp table index
  70. ;*    Destroys:    CX, DI, ES, flags
  71. ;************************************************************************
  72.  
  73. ArpFindIp    proc    near
  74.         mov    di,offset ArpTabIp2
  75.         mov    cx,ARPSLOTS
  76.   ArpFindIpNext:                ; look for matching slot
  77.         repne    scasw
  78.         jnz    ArpFindIpRet
  79.  
  80.         cmp    dx,2*ARPSLOTS-2[di]    ; does IP # first part match?
  81.         jne    ArpFindIpNext        ; - no, look further
  82.  
  83.         sub    di,offset ArpTabIp2+2    ; - yes, compute slot index
  84.         cmp    di,di            ; set zero flag
  85.   ArpFindIpRet:
  86.         ret
  87. ArpFindIp    endp
  88.  
  89.  
  90.  
  91. ;************************************************************************
  92. ;*        ArpFindHw
  93. ;*
  94. ;*    Input:        SI = first word of HW addr (saved)
  95. ;*            DX = second word of HW addr (saved)
  96. ;*            AX = third word of HW addr (saved)
  97. ;*            A PushfDI must be done before calling
  98. ;*    Output:     if found: zero and DI = arp table index
  99. ;*    Destroys:    CX, DI, ES, flags
  100. ;************************************************************************
  101.  
  102. ArpFindHw    proc    near
  103.         mov    di,offset ArpTabHw3
  104.         mov    cx,ARPSLOTS
  105.   ArpFindHwNext:                ; look for matching slot
  106.         repne    scasw
  107.         jnz    ArpFindHwRet
  108.  
  109.         cmp    dx,2*ARPSLOTS-2[di]    ; does HW second part match?
  110.         jne    ArpFindHwNext        ; - no, look further
  111.  
  112.         cmp    si,4*ARPSLOTS-2[di]    ; does HW first part match?
  113.         jne    ArpFindHwNext        ; - no, look further
  114.  
  115.         sub    di,offset ArpTabHw3+2    ; - yes, compute slot index
  116.         cmp    di,di            ; set zero flag
  117.   ArpFindHwRet:
  118.         ret                ; zero (found) return
  119. ArpFindHw    endp
  120.  
  121.  
  122.  
  123. ;************************************************************************
  124. ;*        ArpPutHwAd
  125. ;*
  126. ;*    Input:        SI = pointer to physical address (saved)
  127. ;*            DI = arp table index
  128. ;*            A PushfDI must be done before calling
  129. ;*    Destroys:    CX, DI, flags
  130. ;************************************************************************
  131.  
  132. ArpPutHwAd    proc    near
  133.         push    si
  134.  
  135.         mov    cx,[si]         ; put reverse search
  136.         mov    ArpTabHw1[di],cx    ;   hw addr into slot
  137.         mov    cx,[si+2]
  138.         mov    ArpTabHw2[di],cx
  139.         mov    cx,[si+4]
  140.         mov    ArpTabHw3[di],cx
  141.  
  142.         call    CurrentTicks        ; get current ticks value
  143.         mov    ArpTabTr[di],cx
  144.  
  145.         mov    cx,ArpTabFlags[di]
  146.         and    cl,not USE_SNAP
  147.         or    cl,[bx].dSnap        ; remember if snaps used
  148.         mov    ArpTabFlags[di],cx     ;   by that host
  149.  
  150.         mov    cl,3            ; put hw addr into slot
  151.         shl    di,cl
  152.         lea    di,ArpTabHwAdr[di]
  153.         mov    cx,Hlen
  154.         push    cs
  155.         pop    es
  156.         rep    movsb
  157.         pop    si
  158.         ret
  159. ArpPutHwAd    endp
  160.  
  161.  
  162.  
  163. ;************************************************************************
  164. ;*        ArpPutHwDst
  165. ;*
  166. ;*    Input:        DX = first word of IP # (saved)
  167. ;*            AX = second word of IP # (saved)
  168. ;*    Output:     if found: zero, HW dst addr copied to pkt and CX = 0
  169. ;*    Destroys:    CX, SI, DI, ES, flags
  170. ;************************************************************************
  171.  
  172. ArpPutHwDst    proc    near
  173.         PushfDI
  174.  
  175.         call    ArpFindIp        ; IP # in arp table?
  176.         jnz    ArpPutHwRet        ; - no, non-zero (not found)
  177.  
  178.         mov    cx,ArpTabFlags[di]     ; use snap if neeeded
  179.         and    cl,USE_SNAP
  180.         mov    [bx].dSnap,cl        ;   by dst host
  181. if RFCC
  182.         push    ax
  183.         call    CurrentTicks
  184.         mov    ax,ArpTabSqDelay[di]    ; move sq delay to descriptor
  185.         mov    [bx].dSqDelay,ax
  186.         dec    ax            ; any delay?
  187.         js    ArpNoSqDelay
  188.         mov    ax,ArpTabTrSq[di]    ; - yes
  189.         add    ax,18            ; has one second has passed
  190.         cmp    ax,cx            ;   since we last decremented
  191.         jns    ArpNoSqDelay        ;   the delay value?
  192.         mov    ArpTabTrSq[di],cx
  193.         dec    ArpTabSqDelay[di]    ; - yes, one millisecond off
  194.   ArpNoSqDelay:
  195.         pop    ax
  196. endif ; RFCC
  197.         mov    cl,3            ; - yes, copy HW addr
  198.         shl    di,cl
  199.         lea    si,ArpTabHwAdr[di]
  200.         mov    di,[bx].dPtrPhys
  201.         mov    cx,Hlen
  202.         push    cs
  203.         pop    es
  204.         rep    movsb
  205.  
  206.         PopfEI
  207.         cmp    di,di            ; zero (found) return
  208.         ret
  209.  
  210.   ArpPutHwRet:
  211.         PopfEI
  212.         dec    cx            ; non-zero return
  213.         ret
  214. ArpPutHwDst    endp
  215.  
  216.  
  217.  
  218. ;************************************************************************
  219. ;*        ArpPutNew
  220. ;*
  221. ;*    Input:        DX = first word of IP # (saved)
  222. ;*            AX = second word of IP # (saved)
  223. ;*            SI = pointer to physical address (saved)
  224. ;*    Destroys:    CX, DI, ES, flags
  225. ;************************************************************************
  226.  
  227. ArpPutNew    proc    near
  228.         PushfDI
  229.  
  230.         call    ArpFindIp        ; already have IP # ?
  231.         jz    ArpPutHere        ; - yes, update hw addr
  232.   ArpPutWrap:                    ; - no, find next slot
  233.         mov    di,ArpPutSlot
  234.         add    di,2            ; advance index two bytes
  235.  
  236.         cmp    di,2*ARPSLOTS        ; end of arp table?
  237.         jb    ArpPut
  238.  
  239.         mov    di,ARPMYIDX+2        ; preserve bcast mappings
  240.   ArpPut:                    ;   (first slots)
  241. if TBLBUILD
  242.         push    si
  243.         mov    si,di
  244.         add    si,2
  245.         cmp    si,2*ARPSLOTS
  246.         jb    ArpPut2
  247.         mov    si,ARPMYIDX+2
  248.   ArpPut2:
  249.         mov    cx,ArpTabTr[di]
  250.         sub    cx,ArpTabTr[si]
  251.         js    ArpPut3
  252.         mov    di,si            ; use elder of next 2 slots
  253.   ArpPut3:
  254.         pop    si
  255. endif ; TBLBUILD
  256.         mov    ArpPutSlot,di
  257.         mov    ArpTabIp1[di],dx    ; put IP # into slot
  258.         mov    ArpTabIp2[di],ax
  259.         xor    cx,cx            ; clear other fileds
  260.         mov    ArpTabFlags[di],cx
  261.         mov    ArpTabSqDelay[di],cx
  262.   ArpPutHere:
  263.         call    ArpPutHwAd        ; put HW addr into slot
  264.  
  265.         PopfEI
  266.         ret
  267. ArpPutNew    endp
  268.  
  269.  
  270.  
  271. ;************************************************************************
  272. ;*        SendArpReq
  273. ;*
  274. ;*    Input:        DX = first word of IP # (saved)
  275. ;*            AX = second word of IP # (saved)
  276. ;*            BX = IP description buffer ptr (saved)
  277. ;*    Output:     Zero and CX = 0 if OK
  278. ;*            non-zero and CX = errorcode if error 
  279. ;*    Destroys:    CX, SI, DI, ES, flags
  280. ;************************************************************************
  281.  
  282. SendArpReq    proc    near
  283.         push    dx            ; dx,ax has IP # to arp for
  284.         push    ax
  285.         push    bx            ; save IP descr addr
  286.  
  287.         call    BufAlloc        ; get a buffer
  288.         mov    cx,SERRNOBUF
  289.         jz    SendArpRet
  290.  
  291.         mov    si,offset ArpTabHwAdr    ; put Ether broadcast dst
  292.         mov    cx,Hlen
  293.         push    cs
  294.         pop    es
  295.         rep    movsb
  296.  
  297.         call    MakeSendDescr        ; set up descriptor
  298.  
  299.         call    PutPhysSrc        ; put Ether src addr
  300.  
  301.         push    di
  302.         mov    si,offset ArpFixedPart    ; copy in static arp part
  303.         mov    cx,ArpFixedLen-2*16    ; *test*
  304.         add    cx,H2len
  305.         push    cs
  306.         pop    es
  307.         rep    movsb
  308.  
  309.         sub    di,[bx].dPtrPhys    ; calculate packet length
  310.         mov    [bx].dPktLen,di
  311.  
  312.         pop    di            ; compute addr to dst IP #
  313.         add    di,aArpOffsSrcIp
  314.         add    di,H2Len
  315.  
  316.         mov    [di+4],dx        ; IP # to arp for
  317.         mov    [di+4+2],ax
  318.  
  319.         sub    di,Hlen         ; fill in My IP #
  320.         mov    dx,MyIpNr
  321.         mov    ax,MyIpNr+2
  322.         mov    [di],dx
  323.         mov    [di+2],ax
  324.  
  325.         pop    si            ; IP descr addr
  326.         push    si
  327.  
  328.         mov    cx,[si].dTimOutMsg    ; use application timeout msg
  329.         mov    [bx].dTimOutMsg,cx
  330.  
  331.         mov    cx,[si].dTickTimeout    
  332.         cmp    cx,3*18         ; limit arp timeout
  333.         jbe    SendArpOkTim
  334.         mov    cx,3*18         ;   to 3 seconds or less
  335.   SendArpOkTim:
  336.         mov    [bx].dTickTimeout,cx
  337.  
  338.         mov    [bx].dWaitEvent,GOT_ARPREPLY
  339.  
  340.         call    SendAndWait        ; send arp request packet
  341.  
  342.         call    BufRelease        ; release buffer
  343.   SendArpRet:
  344.         or    cx,cx
  345.         pop    bx            ; restore IP descr addr
  346.         pop    ax            ; restore IP # we ARPed for
  347.         pop    dx
  348.         ret
  349. SendArpReq    endp
  350.  
  351.  
  352.  
  353. ;************************************************************************
  354. ;*        InitArp
  355. ;************************************************************************
  356.  
  357. InitArp     proc    near
  358.         push    ds
  359.         mov    ax,1ffh         ; driver_info
  360.         int_pkt
  361.         pop    ds
  362.  
  363.         call    fatal_error
  364.  
  365.         mov    ah,2            ; access all packets.
  366.         mov    al,ch            ; their class from driver_info().
  367.         mov    byte ptr ArpBuf.iArpHtype+1,al
  368.         mov    bx,dx            ; their type from driver_info().
  369.         mov    dl,cl            ;their number from driver_info().
  370.         mov    cx,2            ;type length of two.
  371.         mov    si,offset ArpType
  372.         push    cs            ;es:di -> our receiver.
  373.         pop    es
  374.         mov    di,offset ArpRecv
  375.  
  376.         push    ds
  377.         int_pkt
  378.         pop    ds
  379.  
  380.         call    fatal_error
  381.  
  382.         mov    ArpHandle,ax
  383.  
  384.         mov    bx,ax
  385.         push    cs
  386.         pop    es
  387.         mov    di,offset MyHwAd
  388.         mov    cx,15
  389.         mov    ah,6            ; get my Hw addr
  390.  
  391.         push    ds
  392.         int_pkt
  393.         pop    ds
  394.  
  395.         call    fatal_error
  396.  
  397.         mov    ArpBuf.iArpHlen,cl    ; save Hw address length
  398.         mov    Hlen,cx
  399.         shl    cx,1
  400.         mov    H2Len,cx
  401.  
  402.         ret
  403. InitArp     endp
  404.  
  405.  
  406.  
  407. ;************************************************************************
  408. ;*        BuildRecDescr
  409. ;************************************************************************
  410.  
  411. BuildRecDescr    proc    near
  412.         mov    bx,si
  413.         mov    ax,si
  414.         add    ax,cx            ; end of packet limit
  415.  
  416.         sub    bx,2
  417.         mov    bx,[bx]         ; addr of descriptor
  418.  
  419.         mov    [bx].dPktLen,cx     ; fill in descriptor info
  420.         mov    [bx].dPktEnd,ax
  421.  
  422.         add    si,H2Len
  423.         mov    ax,[si]         ; type/length field
  424.         xchg    ah,al
  425.  
  426.         xor    dl,dl
  427.         cmp    ax,GIANT        ; if 802.3 pkt
  428.         jbe    BuildHpOrSnap        ;   do special handling
  429.   BuildNotSnap:
  430.         mov    [bx].dSnap,dl
  431.         lea    di,[si+2]
  432.         mov    [bx].dPtrIp,di        ; di must point to IP hdr
  433.         ret
  434.  
  435.   BuildHpOrSnap:
  436.   BuildSnap:
  437.         inc    dl            ; -no, assumed to be snap
  438.         add    si,SNAPLEN        ; skip over snap bytes
  439.         jmp    short BuildNotSnap
  440. BuildRecDescr    endp
  441.  
  442.  
  443.  
  444. ;************************************************************************
  445. ;*        ARP receiver                        *
  446. ;************************************************************************
  447.  
  448. ArpRecv:
  449.         pushf                ; set segment registers
  450.         push    ds
  451.         mov    dx,cs
  452.         mov    ds,dx
  453.         mov    es,dx
  454.         cld
  455.  
  456.         or    ax,ax            ; first or second call?
  457.         jne    ArpRecv_1        ; - second, we've got data
  458.                         ; - first, they want a buf
  459.         cmp    cx,GIANT        ; packet too long?
  460.         ja    ArpRecTooBig
  461. if PINGCLIENT
  462.         cmp    cx,BUFBODYSML
  463.         ja    ArpRecBig
  464.  
  465.         call    BufAlSml
  466.         jz    ArpRecBig
  467.         pop    ds
  468.         popf
  469.         retf
  470.  
  471.   ArpRecBig:
  472. endif ; PINGCLIENT
  473.         call    BufAlloc        ; get a receive buffer
  474.         jz    ArpRecNoBuf
  475.   ArpRecRet0:
  476.         pop    ds
  477.         popf
  478.         retf
  479.  
  480. if DEBUG
  481.   DbgArpRecv:
  482.         or    GenFlags,DBGINTERR
  483. endif ; DEBUG
  484.   ArpRecNoBuf:
  485.   ArpRecTooBig:
  486.         xor    di,di            ; no buffer available
  487.         mov    es,di
  488.         jmp    short ArpRecRet0
  489.  
  490.  
  491.   ArpRecv_1:
  492.         cli                ; switch to our
  493.         mov    word ptr SaveSP,sp    ;   interrupt stack
  494.         mov    word ptr SaveSS,ss
  495.         mov    sp,offset StackEnd
  496.         mov    ss,MySegm
  497.         sti                ; enable interrupts
  498. if DEBUG
  499.         dec    DbgIntCnt        ; double interrupt?
  500.         jnz    DbgArpRecv
  501. endif ; DEBUG
  502.  
  503.         call    BuildRecDescr
  504.  
  505.         cmp    [di].iArpProt,0008h    ; arp IP protocol?
  506.         jne    ArpRecRet
  507.  
  508.         push    di
  509.         mov    di,[bx].dPtrPhys
  510.         add    di,Hlen
  511.         mov    si,[di]
  512.         mov    dx,[di+2]
  513.         mov    ax,[di+4]
  514.         call    ArpFindHw
  515.         pop    si
  516.         jnz    ArpRecNew
  517.  
  518.         cmp    di,ARPMYIDX        ; ignore pkts from bcast or me
  519.         jbe    ArpRecRet        ;   (also helps NDIS)
  520.   ArpRecNew:
  521.         lea    di,[si].iArpMyHwAd
  522.         mov    cx,[si].iArpOp        ; ARP reply?
  523.  
  524.         mov    si,di
  525.         add    di,Hlen
  526.         mov    dx,word ptr [di]    ; get HIS (!) IP # and keep
  527.         mov    ax,word ptr [di+2]    ;   it for a long while
  528.  
  529.         add    di,4
  530.         cmp    di,[bx].dPktEnd     ; big enough to be arp pkt?
  531.         ja    ArpRecRet
  532.  
  533. ; The following test is not according to the ARP RFC. The reason for this
  534. ; divergence is that if we follow the RFC algorithm, anybody that momentarily
  535. ; uses a wrong IP number would disrupt our communication with the original
  536. ; owner of that IP number. This would be true even if the program he uses
  537. ; is nice (NCSA Telnet for example) and starts by sending an ARP packet for 
  538. ; itself to see if anybody will answer (a very good thing to do and this
  539. ; package does so too).
  540. ;
  541. ; We do obey an unsolicited arp reply immediately, other cases of changed
  542. ; hardware address will be taken care of in a minute automagically by the 
  543. ; arp table ageing mechanism, so this package should do well even when moving
  544. ; hosts in a proxy arp environment.
  545.  
  546.         cmp    cx,0200h        ; ARP reply?
  547.         jne    ArpNotReply
  548.  
  549.         PushfDI
  550.         call    ArpFindIp        ; if he is in our ARP table we
  551.         jnz    ArpNotThere
  552.  
  553.         call    ArpPutHwAd        ;   should update his HW addr
  554.   ArpNotThere:
  555.         PopfEI
  556.   ArpNotReply:
  557.         mov    di,si
  558.         add    di,H2Len
  559.         mov    cx,[di+4]
  560.         cmp    cx,MyIpNr        ; is this arp for me?
  561.         jne    ArpRecTbl
  562.         mov    cx,[di+6]
  563.         cmp    cx,MyIpNr+2
  564.         jne    ArpRecTbl
  565.  
  566.         add    di,8
  567.         cmp    di,[bx].dPktEnd
  568.         ja    ArpRecRet
  569.  
  570.         call    ArpPutNew        ; - yes, put his IP # and HW
  571.                         ;     addr into the ARP table
  572.         mov    di,[bx].dPtrIp
  573.         cmp    [di].iArpOp,0100h    ; arp request?
  574.         je    ArpRecReq
  575.  
  576.         or    Events,GOT_ARPREPLY    ; - no, probably a wanted reply
  577.   ArpRecTbl:
  578.  
  579. if TBLBUILD
  580.         test    ArgFlags,MAKE_TABLE
  581.         jnz    ArpRecBld
  582. endif ; TBLBUILD
  583.  
  584.   ArpRecRet:
  585.         call    BufRelease        ; release receive buffer
  586.   ArpRecKeepBuf:
  587. if DEBUG
  588.         inc    DbgIntCnt
  589. endif ; DEBUG
  590.         cli                ; restore previous stack
  591.         mov    sp, word ptr SaveSP
  592.         mov    ss, word ptr SaveSS
  593.         pop    ds
  594.         popf
  595.         retf
  596. if TBLBUILD
  597.   ArpRecBld:
  598.         cmp    FreeBufs.lBufsAvail,NBUFS/4
  599.         jbe    ArpRecRet
  600.  
  601.         test    GenFlags,TBL_READY
  602.         jz    ArpRecRet
  603.  
  604.         mov    si,offset TblToDo
  605.         call    AddToList
  606.         jmp    short ArpRecKeepBuf
  607. endif ; TBLBUILD
  608.  
  609.   ArpRecReq:
  610.         mov    [di].iArpOp,0200h    ; put arp reply code
  611.  
  612.         mov    di,si
  613.         push    di
  614.         mov    cx,Hlen
  615.         add    cx,4
  616.         add    di,cx
  617.         push    cs
  618.         pop    es
  619.         rep    movsb            ; mov arp dst to arp src
  620.         pop    di
  621.  
  622.         mov    si,offset MyHwAd
  623.         mov    cx,Hlen
  624.         rep    movsb            ; put in my HW addr as arp src
  625.  
  626.         mov    cx,MyIpNr
  627.         mov    [di],cx         ; put my IP # to arp src
  628.         mov    si,MyIpNr+2
  629.         mov    [di+2],si
  630.  
  631.         cmp    dx,cx            ; is he stealing my IP # ?
  632.         jne    ArpRecNoSteal
  633.         cmp    ax,si
  634.         jne    ArpRecNoSteal
  635.  
  636.         mov    dx,ArpTabIp1        ; - yes, tell everybody by
  637.         mov    ax,dx            ;   broadcasting my reply
  638.   ArpRecNoSteal:
  639.         mov    [bx].dWaitEvent,0
  640.  
  641.         call    ArpPutHwDst        ; put dst Ether addr fr DX,AX
  642.  
  643.         call    PutPhysSrc        ; put src Ether addr
  644.  
  645.         mov    word ptr [di],0608h    ; arp prot
  646.  
  647.         mov    si,offset SendToDo    ; put buffer on the send list
  648.         call    AddToList        ;   for non-interrupt handling
  649.         jmp    short ArpRecKeepBuf
  650.  
  651. ;========================================================================
  652. ;        endinclude
  653.